package protocol

import (
	"sort"
	"time"

	"gitee.com/doraemon1996/bunny/log"
)

// 消息包组装器
type assembler struct {
	update    time.Time          // 更新时间
	packetMap map[uint64]*Packet // 已经收到的消息包
}

// 实现 structure.Resetable
func (s *assembler) Reset() {
	s.packetMap = nil
}

// 初始化
func (s *assembler) Init() {
	s.update = time.Now()
	s.packetMap = make(map[uint64]*Packet)
}

// 添加消息包
func (s *assembler) Add(pkt *Packet) (complete bool) {
	if _, exist := s.packetMap[pkt.ChunkSeq]; exist {
		log.Errorf("assembler add packet[%X], but sequence %d exist!!! will discard it.", pkt.PacketId, pkt.ChunkSeq)
	} else {
		s.packetMap[pkt.ChunkSeq] = pkt
		s.update = time.Now()
	}

	return uint64(len(s.packetMap)) == pkt.ChunkCount
}

// 获取所有消息包
func (s *assembler) Assemble() (list []*Packet, dataLen int) {
	list = make([]*Packet, 0, len(s.packetMap))

	for _, pkt := range s.packetMap {
		list = append(list, pkt)
		dataLen += len(pkt.Chunk)
	}
	sort.SliceStable(list, func(i, j int) bool {
		return list[i].ChunkSeq < list[j].ChunkSeq
	})
	return
}

// 判断是否过期
func (s *assembler) Expired(now time.Time, duration time.Duration) bool {
	return now.Sub(s.update) > duration
}
